package com.zzyl.nursing.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.core.domain.model.LoginUser;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.SecurityUtils;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.domain.NursingPlan;
import com.zzyl.nursing.domain.NursingTask;
import com.zzyl.nursing.mapper.NursingTaskMapper;
import com.zzyl.nursing.service.IElderService;
import com.zzyl.nursing.service.INursingPlanService;
import com.zzyl.nursing.service.INursingTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 护理任务定时生成
 * 
 * @author zzyl
 * @date 2024-09-27
 */
@Component("createNursingTaskJob")
@Slf4j
public class CreateNursingTaskJob {

    @Autowired
    private INursingTaskService nursingTaskService;
    
    @Autowired
    private IElderService elderService;
    
    @Autowired
    private INursingPlanService nursingPlanService;
    
    @Autowired
    private NursingTaskMapper nursingTaskMapper;

    /**
     * 动态获取用户ID，优先获取当前登录用户，如果没有则返回系统管理员ID
     * 
     * @return 用户ID
     */
    private String getCurrentUserId() {
        try {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            if (ObjectUtils.isNotEmpty(loginUser)) {
                return loginUser.getUserId().toString();
            }
            // 如果没有登录用户（如定时任务场景），返回系统管理员ID
            return "1";
        } catch (Exception e) {
            // 异常情况下也返回系统管理员ID
            log.debug("获取当前用户ID失败，使用系统管理员ID: {}", e.getMessage());
            return "1";
        }
    }

    /**
     * 护理任务定时生成
     * 每天凌晨1点自动为所有老人生成当日的护理任务
     */
    public void createNursingTaskJob() {
        log.info("====== 开始执行护理任务定时生成 ======");
        log.info("执行时间: {}", LocalDateTime.now());
        
        try {
            // 获取当前日期，用于生成任务
            LocalDateTime currentDate = LocalDateTime.now();
            log.info("开始为日期 {} 生成护理任务", currentDate.toLocalDate());
            
            // 这里应该调用业务服务来生成护理任务
            // 由于当前INursingTaskService中没有生成任务的方法，我们先记录日志
            // 后续需要在INursingTaskService中添加generateDailyTasks方法
            
            log.info("护理任务生成逻辑待实现...");
            
            // TODO: 实现护理任务生成逻辑
            // 1. 查询所有有效的老人列表
            // 2. 查询每个老人对应的护理计划
            // 3. 根据护理计划生成当日的护理任务
            // 4. 批量保存护理任务到数据库
            
            int generatedCount = generateNursingTasks(currentDate);
            
            log.info("====== 护理任务定时生成执行完成，共生成 {} 个任务 ======", generatedCount);
            
        } catch (Exception e) {
            log.error("====== 护理任务定时生成执行失败 ======", e);
            throw e; // 重新抛出异常，让定时任务框架记录失败日志
        }
    }
    
    /**
     * 生成护理任务的核心逻辑
     * 
     * @param targetDate 目标日期
     * @return 生成的任务数量
     */
    private int generateNursingTasks(LocalDateTime targetDate) {
        log.info("开始生成 {} 的护理任务", targetDate.toLocalDate());
        
        try {
            int totalGeneratedCount = 0;
            
            // 1. 先查询所有老人，看看数据库中有什么数据
            log.info("1. 查询数据库中所有老人信息");
            List<Elder> allElders = elderService.list();
            log.info("数据库中总老人数量: {}", allElders.size());
            
            // 打印所有老人的状态信息
            for (Elder elder : allElders) {
                log.info("老人: {} (ID:{}), 状态: {}", elder.getName(), elder.getId(), elder.getStatus());
            }
            
            // 临时测试：查询启用状态的老人（状态为1）- 生产环境应改回4
            log.info("2. 临时测试：查询启用状态的老人列表 (status=1)");
            LambdaQueryWrapper<Elder> elderWrapper = new LambdaQueryWrapper<>();
            elderWrapper.eq(Elder::getStatus, 1); // 临时使用1进行测试，正常应该是4表示入住中
            List<Elder> elderList = elderService.list(elderWrapper);
            log.info("找到测试老人数量: {}", elderList.size());
            
            if (elderList.isEmpty()) {
                log.info("没有符合条件的老人，无需生成护理任务");
                return 0;
            }
            
            // 3. 查询所有启用的护理计划（状态为1）
            log.info("3. 查询启用的护理计划");
            NursingPlan planQuery = new NursingPlan();
            planQuery.setStatus(1); // 1表示启用
            List<NursingPlan> nursingPlanList = nursingPlanService.selectNursingPlanList(planQuery);
            log.info("找到启用的护理计划数量: {}", nursingPlanList.size());
            
            if (nursingPlanList.isEmpty()) {
                log.info("没有启用的护理计划，无需生成护理任务");
                return 0;
            }
            
            // 4. 为每个老人根据护理计划生成护理任务
            log.info("4. 开始为老人生成护理任务");
            for (Elder elder : elderList) {
                log.info("为老人 {} (ID:{}) 生成护理任务", elder.getName(), elder.getId());
                
                for (NursingPlan plan : nursingPlanList) {
                    // 创建护理任务
                    NursingTask task = new NursingTask();
                    task.setElderId(elder.getId());
                    task.setElderName(elder.getName());
                    task.setBedNumber(elder.getBedNumber());
                    task.setProjectName(plan.getPlanName());
                    task.setProjectId(plan.getId());
                    
                    // 设置预计服务时间为当天上午9点
                    LocalDateTime estimatedTime = targetDate.toLocalDate().atTime(9, 0);
                    task.setEstimatedServerTime(estimatedTime);
                    
                    // 设置任务状态为待执行
                    task.setStatus(1);
                    
                    // 设置创建时间
                    task.setCreateTime(DateUtils.getNowDate());
                    
                    // 4. 分配护理员（这里简单设置为1，实际应该根据算法分配）
                    task.setNursingId("1");
                    
                    // 5. 保存到数据库
                    try {
                        // 动态设置创建者（优先当前用户，无登录用户时使用系统管理员）
                        task.setCreateBy(getCurrentUserId());
                        task.setRemark("定时任务自动生成");
                        
                        // 实际保存到数据库
                        int result = nursingTaskMapper.insertNursingTask(task);
                        if (result > 0) {
                            log.info("保存护理任务成功: 老人={}, 计划={}", elder.getName(), plan.getPlanName());
                            totalGeneratedCount++;
                        } else {
                            log.error("保存护理任务失败: 老人={}, 计划={}, 返回值={}", elder.getName(), plan.getPlanName(), result);
                        }
                        
                    } catch (Exception e) {
                        log.error("保存护理任务异常: 老人={}, 计划={}", elder.getName(), plan.getPlanName(), e);
                    }
                }
            }
            
            log.info("成功生成 {} 个护理任务", totalGeneratedCount);
            return totalGeneratedCount;
            
        } catch (Exception e) {
            log.error("生成护理任务失败: ", e);
            throw new RuntimeException("生成护理任务失败", e);
        }
    }
} 